DSML10 - MacForth 68000 Disassembler. ( 091484 NDL) This disassembler is based on the MS-BASIC disassembler in Compuserve/MAUG/XA4 (files DSM.V3 and DSM3.O). The following notice is included from DSM.V3: " (c)1984 by R. Nicholson 04/13/84 v.03 " " Permission granted for personal, non-commercial use, " " provided that this notice is included. " The required object table file, which constitutes the guts of the disassembler, is a compacted version of DSM3.O. DSML10 (c)1984 by N. Lebedin CS[74176,2243] 14 SEP 84 Permission granted for personal, non-commercial use, provided that this notice is included. ( load ) ( 091484 NDL) decimal ( All blocks should be loaded in this base. ) 0 ' open 16+ c! ( MacForth Fix 1.101 ) find DSML10 iftrue forget DSML10 ifend : DSML10 ; 4500 minimum.object 300 minimum.vocab ( actual size + 10% ) cr ." Loading disassembler ... " 3 11 thru ." complete." cr ." DSM ( addr1\addr2 -- | disassemble from addr1 to addr2 )" abort ( spare ) ( ?LENGTH ?CHECKSUM ) ( 091484 NDL) : ?LENGTH ( file#\size -- ) swap get.eof ?file.error = not ?dup if 1 sysbeep cr abort" Object file length not valid! " cr then ; base @ hex BD38 constant OBJ.CHKSUM base ! : ?CHECKSUM ( table addr\table size -- ) 0 rot rot over + swap do i w@ xor 2 +loop OBJ.CHKSUM = not ?dup if 1 sysbeep cr abort" Object file checksum not valid! " cr then ; ( LOAD.OBJ.TAB ) ( 091484 NDL) 3424 constant OBJ.TAB.SIZE ( must be exact size of table ) create OBJ.TAB OBJ.TAB.SIZE allot ( object table ) -1 constant OBJ.FILE# ( file number ) : LOAD.OBJ.TAB ( --- | open file, load table, close file ) next.fcb ' OBJ.FILE# ! " DSML10.BIN" OBJ.FILE# assign OBJ.FILE# open ?file.error OBJ.FILE# OBJ.TAB.SIZE ?LENGTH OBJ.TAB OBJ.TAB.SIZE 0 OBJ.FILE# read.virtual ?file.error OBJ.FILE# close ?file.error OBJ.FILE# remove OBJ.TAB OBJ.TAB.SIZE ?CHECKSUM ; LOAD.OBJ.TAB ( BUF ) ( 091484 NDL) { BUF is a string buffer used to post-process the disassembled instruction returned by the machine language subroutine in the object table. } create BUF 1 { size byte } 2 + { high two digits of address } 20 + { extension words (4 * (1 blank + 4 digits)) } 72 + { Disassembled instruction starts at offset 8 in object table and subroutine starts at offset 80. } allot ( >>BUF FIX.BUF ) ( 091484 NDL) : >>BUF ( addr\cnt -- | append cnt bytes at addr to BUF ) swap over BUF dup c@ + 1+ swap cmove ( copy text ) BUF dup c@ rot + swap c! ; ( update size byte ) base @ hex 7F constant 7F_ base ! : FIX.BUF ( --- | reset high bit of each character in BUF ) BUF count over + swap do i c@ 7F_ and i c! loop ; ( CURRENT.INSTR OBJ.xxx ) ( 091484 NDL) variable CURRENT.INSTR ( address of instruction currently being processed ) { locations within object table } OBJ.TAB 02 + constant OBJ.INSTR ( addr of next instruction to disassemble ) OBJ.TAB 06 + constant OBJ.CNT ( number of bytes in disassembled instruction ) OBJ.TAB 08 + constant OBJ.TEXT ( disassembled instruction ) OBJ.TAB 80 + constant OBJ.SUBR ( disassembler subroutine ) ( EXTENSION.WORDS>>BUF ) ( 091484 NDL) : EXTENSION.WORDS>>BUF { --- | put extension words for current instruction (or blanks) in BUF } OBJ.INSTR @ CURRENT.INSTR @ - 2/ 1- ( -- number of extension words ) 4 0 do dup i > if CURRENT.INSTR @ i 1+ 2* + w@ <# # # # # bl hold #> else " " ( five blanks ) count then >>BUF loop drop ( number of extension words -- ) ; ( TEXT>BUF ) ( 091484 NDL) -16 constant DROP4 ( shift-count to shift out low 4 hex digits ) 10 constant FOO ( length of first part of disassembled instruction ) : TEXT>BUF ( --- | post-process disassembled instruction ) ( high two digits of address of instruction ) CURRENT.INSTR @ DROP4 scale <# # # #> >>BUF ( low four digits of address, ": " and opcode word ) OBJ.TEXT FOO >>BUF ( extension words or blanks ) EXTENSION.WORDS>>BUF ( operand field ) OBJ.TEXT FOO + OBJ.CNT w@ FOO - >>BUF ; ( INIT.BUF OUTPUT.BUF PROCESS.TEXT ) ( 091484 NDL) : INIT.BUF 0 BUF c! ; ( --- | initialize BUF ) : OUTPUT.BUF cr BUF count type ; ( --- | output BUF ) : PROCESS.TEXT ( --- | post-process and output disassembled instruction ) INIT.BUF ( initialize buffer ) TEXT>BUF ( move text into buffer ) FIX.BUF ( reset high bits of characters in buffer ) OUTPUT.BUF ; ( output the buffer ) ( DSM ) ( 091484 NDL) : DSM ( start\end -- | disassemble from start to end ) swap =cells dup OBJ.INSTR ! ( --- | load start address into object table ) begin 2dup < not while CURRENT.INSTR ! ( next -- | save addr of current instruction ) OBJ.SUBR >jsr ( --- | call disassembler subroutine ) PROCESS.TEXT ( --- | post-process and output disassembled instruction ) OBJ.INSTR @ ( -- next | get addr of next instruction ) repeat ; { Example: hex 401018 40108C DSM } Description of object table (OBJ.TAB) ( 091484 NDL) The object table is structured as follows. Offsets are in decimal and are relative to base of object table. Before call: +02 address of instruction to disassemble (long word) After call: +02 address of next instruction +06 number of bytes in disassembled instruction (word) +08 disassembled instruction (text, detailed below) Not changed: +80 disassembler subroutine (returns via RTS) (cont) Description of object table (continued) ( 091484 NDL) The disassembled instruction has the following format. Offsets are in decimal and are relative to base of object table. +08 low word of instruction address (4 hex digits) +12 colon and blank (": ") +14 opcode word (4 hex digits) +18 two blanks (" ") +20 opcode mnemonic and operand field Note: the high bit of some characters must be reset. Example of disassembled instruction (quotes added here): "1018: 558F SUBQ.L #2,A7" Revision history ( 091484 NDL) 14 SEP 84 - Original released as DSML10